﻿using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml.Linq;

namespace Panorama43Things.Helper
{
    //http://mikehadlow.blogspot.com/2006/05/making-raw-web-service-calls-with.html
    public class CreateWebRequestReturnSoap
    {
        const string SoapEnvelope = @"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body></soap:Body></soap:Envelope>";

        /// <summary>
        /// Is Success if the number of elements in a sequence is greater then zero.
        /// </summary>
        public bool IsSuccess { get; set; }

        /// <summary>
        /// Gets a value that indicates whether the asynchronous operation has completed.
        /// </summary>
        public bool IsCompleted { get; set; }
        /// <summary>
        /// Blocks the current thread until the current System.Threading.WaitHandle receives a signal.
        /// </summary>
        public bool IsWaitComplete { get; set; }
        /// <summary>
        /// Load an System.Xml.Linq.XElement from a string that contains XML, optionally preserving white space and retaining line information.
        /// </summary>
        public XElement ResultXml { get; set; }

        /// <summary>
        /// Gets a value that indicates whether the asynchronous operation completed synchronously.
        /// </summary>
        public bool IsRequestCompletedSynchronously { get; set; }

        private static XDocument CreateSoapEnvelope(string content)
        {
            var sb = new StringBuilder(SoapEnvelope);
            sb.Insert(sb.ToString().IndexOf("</soap:Body>"), content);

            XDocument soapEnvelopeXml = XDocument.Parse(sb.ToString());

            return soapEnvelopeXml;
        }

        private static HttpWebRequest CreateWebRequest(string url, NetworkCredential credentials)
        {
            const string action = "http://schemas.microsoft.com/sharepoint/soap/GetWebCollection";
            var req = (HttpWebRequest)WebRequest.Create(url);
            req.Credentials = credentials;
            req.Headers["SOAPAction"] = action;
            req.ContentType = "text/xml;charset=\"utf-8\"";
            req.Accept = "text/xml";
            req.Method = "POST";
            return req;
        }

        private void InsertSoapEnvelopeIntoWebRequest(XDocument soapEnvelopeXml, HttpWebRequest webRequest)
        {
            webRequest.BeginGetRequestStream(asynchronousResult =>
            {
                var request = (HttpWebRequest)asynchronousResult.AsyncState;
                Stream postStream = request.EndGetRequestStream(asynchronousResult);
                soapEnvelopeXml.Save(postStream);
                postStream.Close();
                request.BeginGetResponse(GetResponseCallback, request);
            }, webRequest);
        }

        public CreateWebRequestReturnSoap(string url)
        {
            HttpWebRequest request = CreateWebRequest(url, null);
            XDocument soapEnvelope = CreateSoapEnvelope("<GetWebCollection xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\" />");
            InsertSoapEnvelopeIntoWebRequest(soapEnvelope, request);
        }

        //public CreateWebRequestReturnSoap(string url, NetworkCredential credentials)
        //{
        //    HttpWebRequest request = CreateWebRequest(url, credentials);
        //    XDocument soapEnvelope = CreateSoapEnvelope("<GetWebCollection xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\" />");
        //    InsertSoapEnvelopeIntoWebRequest(soapEnvelope, request);
        //}

        private void GetResponseCallback(IAsyncResult asynchronousResult)
        {
            var request = (HttpWebRequest)asynchronousResult.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
            Stream streamResponse = response.GetResponseStream();

            var streamRead = new StreamReader(streamResponse);
            string responseString = streamRead.ReadToEnd();

            IsRequestCompletedSynchronously = asynchronousResult.CompletedSynchronously;
            ResultXml = XElement.Parse(responseString, LoadOptions.None);
            IsSuccess = ResultXml.Elements().Count() > 0;
            IsCompleted = asynchronousResult.IsCompleted;
            streamResponse.Close();
            streamRead.Close();
            response.Close();

        }
    }
}
